import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import io.netty.handler.codec.http.QueryStringDecoder;
import io.netty.util.CharsetUtil;

import java.util.List;
import java.util.Map;

/**
 * 请求控制器
 *
 * @author xiuwei
 * @date 2021/11/26
 */
public class RequestController {


    private static class LazyHolder {
        private static final RequestController INSTANCE = new RequestController();
    }

    public static final RequestController getInstance() {
        return RequestController.LazyHolder.INSTANCE;
    }

    private RequestController() {
    }

    @RequestHandlerFunction(requestType = RequestControllerManager.RequestMethodType.GET, requestUrl = "/addConstantPoint")
    public RequestHandler addConstantPoint() {
        return (request) -> {
            QueryStringDecoder decoder = new QueryStringDecoder(request.uri());
            Map<String, List<String>> params = decoder.parameters();
            String point = null;
            String value = null;
            if (params.containsKey("point")) {
                point = params.get("point").get(0);
            }
            if (params.containsKey("value")) {
                value = params.get("value").get(0);
            }
            if (point != null && value != null) {
                PointDataContainer.getInstance().add2PointDataMap(new PointDataConstantValue(Integer.valueOf(point), value));
                return addConstantPoint().getTextResponse("ok");
            } else {
                return addConstantPoint().getTextResponse("err");
            }
        };
    }

    @RequestHandlerFunction(requestType = RequestControllerManager.RequestMethodType.GET, requestUrl = "/addCalculatorPoint")
    public RequestHandler addCalculatorPoint() {
        return (request) -> {
            QueryStringDecoder decoder = new QueryStringDecoder(request.uri());
            Map<String, List<String>> params = decoder.parameters();
            String point = null;
            String value = null;
            if (params.containsKey("point")) {
                point = params.get("point").get(0);
            }
            if (params.containsKey("value")) {
                value = params.get("value").get(0);
            }
            if (point != null && value != null) {
                PointDataContainer.getInstance().add2PointDataMap(new PointDataCalculator(Integer.valueOf(point), value));
                return addCalculatorPoint().getTextResponse("ok");
            } else {
                return addCalculatorPoint().getTextResponse("err");
            }
        };
    }


    @RequestHandlerFunction(requestType = RequestControllerManager.RequestMethodType.GET, requestUrl = "/deletePoint")
    public RequestHandler deletePoint() {
        return (request) -> {
            QueryStringDecoder decoder = new QueryStringDecoder(request.uri());
            Map<String, List<String>> params = decoder.parameters();
            String point = null;
            if (params.containsKey("point")) {
                point = params.get("point").get(0);
            }
            if (point != null) {
                PointDataContainer.getInstance().deleteFromPointDataMap(Integer.valueOf(point));
                ProtocolDataContainer.getInstance().deleteData(Integer.valueOf(point));
                return addCalculatorPoint().getTextResponse("ok");
            } else {
                return addCalculatorPoint().getTextResponse("err");
            }
        };
    }


    @RequestHandlerFunction(requestType = RequestControllerManager.RequestMethodType.GET, requestUrl = "/")
    public RequestHandler index() {
        return (request) -> index().getTextResponse(GetStaticFileUtils.getFileContext("slaver.html"));
    }


    @RequestHandlerFunction(requestType = RequestControllerManager.RequestMethodType.GET, requestUrl = "/getAllPoints")
    public RequestHandler getAllPoints() {
        return (request) -> index().getTextResponse(PointDataContainer.getInstance().getAllPoint().toJSONString());
    }

    @RequestHandlerFunction(requestType = RequestControllerManager.RequestMethodType.GET, requestUrl = "/favicon.ico")
    public RequestHandler icon() {
        return (request) -> icon().getIcon(GetStaticFileUtils.getFileStream("favicon.ico"));
    }

    @RequestHandlerFunction(requestType = RequestControllerManager.RequestMethodType.POST, requestUrl = "/uploadConfig")
    public RequestHandler uploadConfig() {
        return (request) -> {
            String bodyStr = request.content().toString(CharsetUtil.UTF_8);
            JSONObject jsonObject = JSONObject.parseObject(bodyStr);
            batchImport(jsonObject);
            return uploadConfig().getTextResponse("yes");
        };
    }

    public void batchImport(JSONObject jsonObject) {
        for (Map.Entry<String, Object> entry : jsonObject.entrySet()) {
            try {
                Integer key = Integer.parseInt(entry.getKey());
                String value = entry.getValue().toString();
                if ("true".equals(value) || "false".equals(value)) {
                    PointDataContainer.getInstance().add2PointDataMap(new PointDataConstantValue(key, value));
                } else {
                    try {
                        Float.parseFloat(value);
                        PointDataContainer.getInstance().add2PointDataMap(new PointDataConstantValue(key, value));
                    } catch (NumberFormatException e) {
                        PointDataContainer.getInstance().add2PointDataMap(new PointDataCalculator(key, value));
                    }
                }
            } catch (Exception e) {
            }
        }
    }

    @RequestHandlerFunction(requestType = RequestControllerManager.RequestMethodType.GET, requestUrl = "/getValues")
    public RequestHandler getValues() {
        return (request) -> getValues().getTextResponse(ProtocolDataContainer.getInstance().getValues().toJSONString());
    }


}
